﻿using Micro.Core.Options;
using Micro.Core.Packages;
using Micro.Core.Packages.Builders;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Micro.Core.Configs;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Hosting;

namespace Microsoft.Extensions.DependencyInjection
{

    public static class ServiceExtensions
    {

        public static IServiceCollection AddMicroBuilder(this IServiceCollection services, Action<IMicroBuilder> microBuilderAction, Action<MicroOptions> optionAction = null)
        {
            IMicroBuilder microBuilder= services.AddMicro(optionAction);
            microBuilderAction?.Invoke(microBuilder);

            microBuilder.AddPackServicesed(services);
            return services;
        }


        #region IServiceCollection

        /// <summary>
        /// 创建Micro构建器，开始构建Micro服务
        /// </summary>
        public static IMicroBuilder AddMicro(this IServiceCollection services, Action<MicroOptions> optionAction = null)
        {

            services.GetOrAddSingletonInstance(() => new AppsettingConfigs(services.GetConfiguration()));

            IMicroBuilder builder = services.GetOrAddSingletonInstance<IMicroBuilder>(() => new MicroBuilder(services));
            builder.AddCorePack();

            optionAction?.Invoke(builder.Options);

            return builder;
        }

        /// <summary>
        /// 获取<see cref="IConfiguration"/>配置信息
        /// </summary>
        public static IWebHostEnvironment GetWebHostEnvironment(this IServiceCollection services)
        {
            return services.GetSingletonInstanceOrNull<IWebHostEnvironment>();
        }

        /// <summary>
        /// 获取<see cref="IConfiguration"/>配置信息
        /// </summary>
        public static IConfiguration GetConfiguration(this IServiceCollection services)
        {
            return services.GetSingletonInstanceOrNull<IConfiguration>();
        }

        /// <summary>
        /// 获取<see cref="IConfiguration"/>配置信息
        /// </summary>
        public static ConfigurationManager GetConfigurationManager(this IServiceCollection services)
        {
            return GetConfiguration(services) as ConfigurationManager;
        }

        /// <summary>
        /// 获取<see cref="MicroOptions"/>配置信息
        /// </summary>
        public static MicroOptions GetMicroOptions(this IServiceCollection services)
        {
            IConfiguration configuration = services.GetConfiguration();
            return configuration.GetMicroOptions();
        }

        /// <summary>
        /// 判断指定服务类型是否存在
        /// </summary>
        public static bool AnyServiceType(this IServiceCollection services, Type serviceType)
        {
            return services.Any(m => m.ServiceType == serviceType);
        }

        /// <summary>
        /// 替换服务
        /// </summary>
        public static IServiceCollection Replace<TService, TImplement>(this IServiceCollection services, ServiceLifetime lifetime)
        {
            ServiceDescriptor descriptor = new ServiceDescriptor(typeof(TService), typeof(TImplement), lifetime);
            services.Replace(descriptor);
            return services;
        }

        /// <summary>
        /// 如果指定服务不存在，添加指定服务
        /// </summary>
        public static ServiceDescriptor GetOrAdd(this IServiceCollection services, ServiceDescriptor toAdDescriptor)
        {
            ServiceDescriptor descriptor = services.FirstOrDefault(m => m.ServiceType == toAdDescriptor.ServiceType);
            if (descriptor != null)
            {
                return descriptor;
            }

            services.Add(toAdDescriptor);
            return toAdDescriptor;
        }

        /// <summary>
        /// 如果指定服务不存在，创建实例并添加
        /// </summary>
        public static TServiceType GetOrAddSingletonInstance<TServiceType>(this IServiceCollection services, Func<TServiceType> factory) where TServiceType : class
        {
            TServiceType item = GetSingletonInstanceOrNull<TServiceType>(services);
            if (item == null)
            {
                item = factory();
                services.AddSingleton<TServiceType>(item);
            }
            return item;
        }

        /// <summary>
        /// 获取注册服务对象
        /// </summary>
        public static T GetInstanceOrNull<T>(this IServiceCollection services, ServiceLifetime serviceLifetime = ServiceLifetime.Singleton)
        {
            ServiceDescriptor descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(T) && d.Lifetime == serviceLifetime);

            if (descriptor?.ImplementationInstance != null)
            {
                return (T)descriptor.ImplementationInstance;
            }

            if (descriptor?.ImplementationFactory != null)
            {
                return (T)descriptor.ImplementationFactory.Invoke(null);
            }

            return default;
        }

        /// <summary>
        /// 获取单例注册服务对象
        /// </summary>
        public static T GetSingletonInstanceOrNull<T>(this IServiceCollection services)
        {
            //ServiceDescriptor descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(T) && d.Lifetime == ServiceLifetime.Singleton);
            
            //if (descriptor?.ImplementationInstance != null)
            //{
            //    return (T)descriptor.ImplementationInstance;
            //}

            //if (descriptor?.ImplementationFactory != null)
            //{
            //    return (T)descriptor.ImplementationFactory.Invoke(null);
            //}

            return GetInstanceOrNull<T>(services);
        }


        /// <summary>
        /// 获取单例注册服务对象
        /// </summary>
        public static bool IsInstance<T>(this IServiceCollection services, ServiceLifetime serviceLifetime)
        {
            ServiceDescriptor descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(T) && d.Lifetime == serviceLifetime);

            if (descriptor?.ImplementationInstance != null)
            {
                return true;
            }

            if (descriptor?.ImplementationFactory != null)
            {
                return true;
            }

            return false;
        }


        ///// <summary>
        ///// 获取单例注册服务对象
        ///// </summary>
        //public static bool IsServiceDescriptor<T>(this IServiceCollection services)
        //{
        //    ServiceDescriptor descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(T) && d.Lifetime == ServiceLifetime.Singleton);

        //    if (descriptor?.ImplementationInstance != null)
        //    {
        //        return (T)descriptor.ImplementationInstance;
        //    }

        //    if (descriptor?.ImplementationFactory != null)
        //    {
        //        return (T)descriptor.ImplementationFactory.Invoke(null);
        //    }

        //    return default;
        //}

        /// <summary>
        /// 获取单例注册服务对象
        /// </summary>
        public static T GetSingletonInstance<T>(this IServiceCollection services)
        {
            var instance = services.GetSingletonInstanceOrNull<T>();
            if (instance == null)
            {
                throw new InvalidOperationException($"无法找到已注册的单例服务：{typeof(T).AssemblyQualifiedName}");
            }

            return instance;
        }

        

        #endregion

        #region IServiceProvider

        /// <summary>
        /// 从服务提供者中获取MicroOptions
        /// </summary>
        public static MicroOptions GetMicroOptions(this IServiceProvider provider)
        {
            return provider.GetService<IOptions<MicroOptions>>()?.Value;
        }

        

        /// <summary>
        /// 获取指定类型的日志对象
        /// </summary>
        /// <typeparam name="T">非静态强类型</typeparam>
        /// <returns>日志对象</returns>
        public static ILogger<T> GetLogger<T>(this IServiceProvider provider)
        {
            ILoggerFactory factory = provider.GetService<ILoggerFactory>();
            return factory.CreateLogger<T>();
        }

        /// <summary>
        /// 获取指定类型的日志对象
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="type">指定类型</param>
        /// <returns>日志对象</returns>
        public static ILogger GetLogger(this IServiceProvider provider, Type type)
        {
            ILoggerFactory factory = provider.GetService<ILoggerFactory>();
            return factory.CreateLogger(type);
        }

        /// <summary>
        /// 获取指定对象类型的日志对象
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="instance">要获取日志的类型对象，一般指当前类，即this</param>
        public static ILogger GetLogger(this IServiceProvider provider, object instance)
        {
            ILoggerFactory factory = provider.GetService<ILoggerFactory>();
            return factory.CreateLogger(instance.GetType());
        }

        /// <summary>
        /// 获取指定名称的日志对象
        /// </summary>
        public static ILogger GetLogger(this IServiceProvider provider, string name)
        {
            ILoggerFactory factory = provider.GetRequiredService<ILoggerFactory>();
            return factory.CreateLogger(name);
        }

       

        /// <summary>
        /// 获取所有模块信息
        /// </summary>
        public static BasePackage[] GetAllPacks(this IServiceProvider provider)
        {
            BasePackage[] packs = provider.GetServices<BasePackage>().OrderBy(m => m.Level).ThenBy(m => m.Order).ThenBy(m => m.GetType().FullName).ToArray();
            return packs;
        }

        /// <summary>
        /// 获取当前用户
        /// </summary>
        public static ClaimsPrincipal GetCurrentUser(this IServiceProvider provider)
        {
            try
            {
                IPrincipal user = provider.GetService<IPrincipal>();
                return user as ClaimsPrincipal;
            }
            catch
            {
                return null;
            }
        }


        /// <summary>
        /// 执行<see cref="ServiceLifetime.Scoped"/>生命周期的业务逻辑
        /// </summary>
        public static void ExecuteScopedWork(this IServiceProvider provider, Action<IServiceProvider> action)
        {
            using (IServiceScope scope = provider.CreateScope())
            {
                action(scope.ServiceProvider);
            }
        }

        /// <summary>
        /// 异步执行<see cref="ServiceLifetime.Scoped"/>生命周期的业务逻辑
        /// </summary>
        public static async Task ExecuteScopedWorkAsync(this IServiceProvider provider, Func<IServiceProvider, Task> action)
        {
            using (IServiceScope scope = provider.CreateScope())
            {
                await action(scope.ServiceProvider);
            }
        }

        /// <summary>
        /// 执行<see cref="ServiceLifetime.Scoped"/>生命周期的业务逻辑，并获取返回值
        /// </summary>
        public static TResult ExecuteScopedWork<TResult>(this IServiceProvider provider, Func<IServiceProvider, TResult> func)
        {
            using (IServiceScope scope = provider.CreateScope())
            {
                return func(scope.ServiceProvider);
            }
        }

        /// <summary>
        /// 执行<see cref="ServiceLifetime.Scoped"/>生命周期的业务逻辑，并获取返回值
        /// </summary>
        public static async Task<TResult> ExecuteScopedWorkAsync<TResult>(this IServiceProvider provider, Func<IServiceProvider, Task<TResult>> func)
        {
            using (IServiceScope scope = provider.CreateScope())
            {
                return await func(scope.ServiceProvider);
            }

        }

        #endregion

    }
}
